﻿using Cloud.Update.Core.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace Cloud.Update.Core.Utils
{
    public class DownloadUtil
    {
        private string url; //文件下载网络地址
        private string path; //文件下载位置，如d:/download
        private string filename; //文件名，如test.jpg
        private string fileId; //文件ID，文件唯一标识，一般为UUID

        public delegate void ProgressChangedHandler(DownLoadModel progress);
        public event ProgressChangedHandler ProgressChanged;
        public delegate void DownloadFinishHandler(bool isSuccess, string downloadPath, string fileId, string msg = null, string name = null);
        public event DownloadFinishHandler DownloadFinish;
        protected virtual void OnProgressChanged(DownLoadModel progress)
        {
            ProgressChanged?.Invoke(progress);
        }

        protected virtual void OnDownloadFinish(bool isSuccess, string downloadPath, string fileId, string msg = null,string name = null)
        {
            DownloadFinish?.Invoke(isSuccess, downloadPath, fileId, msg,name);
        }

        //通过网络链接直接下载任意文件
        public DownloadUtil(string url, string path, string filename, string fileId)
        {
            this.url = url;
            this.path = path;
            this.filename = filename;
            this.fileId = fileId;
        }

        public void Download()
        {
            Download(url, path, filename, fileId);
        }
        private void Download(string url, string path, string filename, string fileId)
        {

            if (!Directory.Exists(path))   //判断文件夹是否存在
                Directory.CreateDirectory(path);
            path = path + "/" + filename;
            string tempFile = path + ".temp"; //临时文件
            if (File.Exists(tempFile))
            {
                File.Delete(tempFile);    //存在则删除
            }
            if (File.Exists(path))
            {
                File.Delete(path);    //存在则删除
            }
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            string[] nameArr = url.Split('/');
            string name = nameArr[nameArr.Length - 1];
            name = name.Replace(".", "").Replace("zip", "");

            try
            {

                //创建临时文件
                using (FileStream fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                {
                    //HttpWebRequest request = null;
                    if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                    {
                        // 这里设置了协议类型。把SSL验证的设置写到HttpRequect创建之前
                        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(RemoteCertificateValidate);
                        ServicePointManager.CheckCertificateRevocationList = true;
                        ServicePointManager.DefaultConnectionLimit = 100;
                        ServicePointManager.Expect100Continue = true;
                        //.Net4.0
                        ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
                        //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
                        //               | (SecurityProtocolType)0x300 //Tls11
                        //               | (SecurityProtocolType)0xC00; //Tls12
                        request = WebRequest.Create(url) as HttpWebRequest;
                        request.ProtocolVersion = HttpVersion.Version11;
                        request.KeepAlive = false;
                    }
                    else
                    {
                        request = WebRequest.Create(url) as HttpWebRequest;
                    }

                    
                    //发送请求并获取相应回应数据
                    response = request.GetResponse() as HttpWebResponse;
                    //直到request.GetResponse()程序才开始向目标网页发送Post请求
                    using (Stream responseStream = response.GetResponseStream()) {
                        long totalBytes = response.ContentLength; //通过响应头获取文件大小，前提是响应头有文件大小
                        int size;
                        byte[] data = new byte[2048];
                        long totalDownloadedByte = 0;  //总共下载字节数
                        while (true)  //while循环读取响应流
                        {
                            size = responseStream.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                fs.Write(data, 0, size); //写到临时文件
                                totalDownloadedByte += (size / 1024);
                                var totalKb = totalBytes / 1024;
                                var rate = (float)totalDownloadedByte / ((float)totalKb);
                                if (rate > 1)
                                    rate = 1;
                                DownLoadModel downLoad = new DownLoadModel
                                {
                                    FileId = fileId,
                                    TotalSize = totalKb,
                                    CurrentSize = totalDownloadedByte,
                                    ProgressRate = (int)(rate*100),
                                    Name = name,
                                };
                                OnProgressChanged(downLoad);  //下载进度回调
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                if (File.Exists(path))
                {
                    File.Delete(path);    //存在则删除
                }
                if (File.Exists(tempFile))
                    File.Move(tempFile, path); //重命名为正式文件
                OnDownloadFinish(true, path, fileId, null,name);  //下载完成，成功回调
                
            }
            catch (Exception ex)
            {
                OnDownloadFinish(false, null, fileId, ex.Message+url,name);  //下载完成，失败回调
            }
            finally
            {
                
                if (request != null)
                    request.Abort();
                if (response != null)
                    response.Close();               
            }
        }
        ///
        /// 远程证书验证
        ///
        private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
        {
            return true;
        }
    }
}
